import { reactive, ref, toRefs, h } from "vue"
import tool from "@/utils/tool.js"
const { deepCopy, throwError, compileFlatState, uuid } = tool
import settingDropdown from "../components/setting-dropdown.vue"
import source from "@/views/datasource/api/source.js"
import cube from "@/views/datasource/api/cube.js"
import { Message, Message as message } from "@arco-design/web-vue"

export default function useModelData(dataset) {
  const nodeEditRef = ref(null)
  const linkEditRef = ref(null)
  // ****************** [左侧表结构] ****************** //
  const tableList = ref([])
  const tableListLoading = ref(false)
  // ****************** [拖拽节点数据] ****************** //
  const status = reactive({
    stateTree: {}, // 表节点树
    flatState: [], // 拉平的树结构
    dragging: false,
    loading: false,
    dimensionTree: {}, // 维度树
    dimensionTreeFlats: [], // 维度树拉平
    dimensionFields: [],
    measureTree: {}, // 度量树
    measureTreeFlats: [], // 度量树拉平
    measureFields: []
  })
  // ****************** [编辑节点内容缓存] ****************** //
  const currentNodeKey = ref(-1)
  const currentParentNodeKey = ref(-1)
  // ****************** [编辑字段内容] ****************** //
  const fieldStatus = reactive({
    fieldModal: false,
    filedNode: {}
  })
  const previewData = ref([])

  // 节点点击事件
  function handleNodeClick(nodeKey) {
    const node = status.flatState[nodeKey].node
    currentNodeKey.value = nodeKey
    nodeEditRef.value && nodeEditRef.value.open(dataset, node)
  }

  // 保存一个nodeKey的节点fields选中项
  function saveCheckedFields(nodeKey, selections) {
    const node = status.flatState[nodeKey].node
    // 设置字段选中状态
    node.fields.forEach((item) => {
      item._checked = selections.includes(item.field)
    })
    fieldUpdateByTable()
  }

  // 保存已勾选的字段
  function saveSelectedFields(selectedFields) {
    saveCheckedFields(currentNodeKey.value, selectedFields)
  }

  // 保存join keys
  function saveJoinKeys(parentSelectedFields, selectedFields, tableInfo) {
    const { joinType, joinKeys } = tableInfo
    // 保存两个节点勾选项
    saveCheckedFields(currentParentNodeKey.value, parentSelectedFields)
    saveCheckedFields(currentNodeKey.value, selectedFields)
    const node = status.flatState[currentNodeKey.value].node
    node.joinType = joinType
    node.joinKeys = deepCopy(joinKeys)
  }

  // 连接桩点击事件
  function handleLinkClick(nodeKey, parentNodeKey) {
    const node = status.flatState[nodeKey].node
    const parentNode = status.flatState[parentNodeKey].node

    currentNodeKey.value = nodeKey
    currentParentNodeKey.value = parentNodeKey

    linkEditRef.value && linkEditRef.value.open(dataset, node, parentNode)
  }

  // 节点移除事件
  function handleNodeRemove(nodeKey, parentNodeKey) {
    const node = status.flatState[nodeKey].node
    // 执行移除节点操作
    if (node.nodeKey === 0) {
      // 根节点删除
      status.stateTree = {}
    } else {
      const parentNode = status.flatState[parentNodeKey].node
      const index = parentNode.children.indexOf(node)
      parentNode.children.splice(index, 1)
    }
    updateStateTree()
    fieldUpdateByTable()
  }

  // 拖拽增加子节点
  async function handleNodeDrop(parentNodeKey, tableId) {
    const parentNode = status.flatState[parentNodeKey].node
    const { fields: parentFields } = parentNode
    const table = tableList.value.find((v) => v.id === tableId)
    const tableFields = await source.getFieldsList({
      datasource_id: table.datasource_id,
      table_name: table.table_name
    })
    table.fields = tableFields.data
    const { id, title, tableName, fields, schemaName } = table
    if (!table) return
    // 执行新增节点操作
    const children = parentNode.children || []
    const joinKeys = []
    // 拼接默认连接join
    if (parentFields.length && fields.length) {
      joinKeys.push({
        sourceField: parentFields[0].field,
        targetField: fields[0].field
      })
    }
    children.push({
      id,
      tableId: id,
      title,
      schemaName,
      tableName,
      fields: fields.map((i) => ({
        ...i,
        tableName,
        fieldId: "f_" + uuid(),
        _checked: true
      })),
      joinType: "LEFT_OUTER_JOIN",
      joinKeys
    })
    parentNode.children = children
    updateStateTree()
    fieldUpdateByTable()
  }

  // 增加根节点
  async function handleEmptyDrop(tableId) {
    const table = tableList.value.find((v) => v.id === tableId)
    const tableFields = await source.getFieldsList({
      datasource_id: table.datasource_id,
      table_name: table.table_name
    })
    table.fields = tableFields.data
    const { id, title, tableName, fields, schemaName } = table
    if (!table) return
    status.stateTree = {
      id,
      tableId: id,
      schemaName,
      title,
      tableName,
      fields: fields.map((i) => ({
        ...i,
        tableName,
        fieldId: "f_" + uuid(),
        _checked: true
      }))
    }
    updateStateTree()
    fieldUpdateByTable()
  }

  // 维度度量树
  function renderContent({ root, node, data }) {
    const inline = [h("span", [`${data.title}${data.field ? "-(" + data.field + ")" : ""}`])]
    if (data.nodeType !== "root") {
      inline.push(h(settingDropdown, { data, onCommand: handleDmCommand }))
    }
    return h("span", { style: { width: "100%", fontSize: "12px" }, flex: "main:justify" }, inline)
  }

  // 维度度量，字段操作函数
  function handleDmCommand({ name, node }) {
    console.log(name, node)
    if (name === "edit") {
      fieldStatus.fieldModal = true
      fieldStatus.filedNode = {
        field: node.field,
        title: node.title,
        nodeKey: node.nodeKey,
        type: node.type
      }
    } else if (name === "convert") {
      convertField(node)
    } else if (name === "delete") {
      removeField(node)
    }
  }

  // 保存字段
  function saveField() {
    const { title, type, nodeKey } = fieldStatus.filedNode
    const realNode = type === "D" ? status.dimensionTreeFlats[nodeKey].node : status.measureTreeFlats[nodeKey].node
    realNode.title = title
    fieldStatus.fieldModal = false
  }

  // 字段转换函数
  function convertField(node) {
    // 维度转换度量
    if (node.type === "D") {
      // 维度树节点移除当前children
      const parentKey = status.dimensionTreeFlats[node.nodeKey].parent
      const parent = status.dimensionTreeFlats[parentKey].node
      if (parent !== undefined) {
        const index = parent.children.indexOf(node)
        parent.children.splice(index, 1)
      }
      // 度量树新增一个child
      const children = status.measureTree.children || []
      children.push({
        fieldId: node.fieldId,
        field: node.field,
        tableId: node.tableId,
        tableName: node.tableName,
        title: node.title,
        dataType: node.dataType,
        nodeType: "attribute",
        aggregate: node.aggregate || "SUM",
        format: node.format || "",
        type: "M"
      })
      status.measureTree.children = children

      status.measureTree = deepCopy(status.measureTree)
    } else {
      // 度量转换维度
      // 度量树节点移除当前children
      const parentKey = status.measureTreeFlats[node.nodeKey].parent
      const parent = status.measureTreeFlats[parentKey].node
      if (parent !== undefined) {
        const index = parent.children.indexOf(node)
        parent.children.splice(index, 1)
      }
      // 维度树新增一个child
      const children = status.dimensionTree.children || []
      children.push({
        fieldId: node.fieldId,
        field: node.field,
        tableId: node.tableId,
        tableName: node.tableName,
        title: node.title,
        dataType: node.dataType,
        nodeType: "attribute",
        aggregate: node.aggregate || "SUM",
        format: node.format || "",
        type: "D"
      })
      status.dimensionTree.children = children
      status.dimensionTree = deepCopy(status.dimensionTree)
    }
    updateFieldState({
      dimension: status.dimensionTree,
      measure: status.measureTree
    })
  }

  // 新增计算字段
  function addCalField(node) {
    if (node.type === "D") {
      const children = status.dimensionTree.children || []
      children.unshift({
        fieldId: node.fieldId,
        field: node.field,
        tableId: node.tableId,
        tableName: node.tableName,
        title: node.title,
        dataType: node.dataType,
        nodeType: "attribute",
        aggregate: node.aggregate || "SUM",
        format: node.format || "",
        type: "D"
      })
      status.dimensionTree.children = children
      status.dimensionTree = deepCopy(status.dimensionTree)
    } else {
      const children = status.measureTree.children || []
      children.unshift({
        fieldId: node.fieldId,
        field: node.field,
        tableId: node.tableId,
        tableName: node.tableName,
        title: node.title,
        dataType: node.dataType,
        nodeType: "attribute",
        aggregate: node.aggregate || "SUM",
        format: node.format || "",
        type: "M"
      })
      status.measureTree.children = children
      status.measureTree = deepCopy(status.measureTree)
    }
    updateFieldState({
      dimension: status.dimensionTree,
      measure: status.measureTree
    })
  }
  // 移除一个字段项
  function removeField(node) {
    const { tableId, fieldId } = node
    // 查找上方表
    const tableNode = status.flatState.find((v) => v.node.tableId === tableId || v.node.id === tableId)
    const tableKey = tableNode.nodeKey
    const fields = tableNode.node.fields.filter((i) => i._checked && i.fieldId !== fieldId).map((v) => v.field)

    saveCheckedFields(tableKey, fields)
  }

  // 更新树数据
  const updateStateTree = () => {
    status.flatState = compileFlatState(status.stateTree)
  }

  // 根据上方表节点更新字段
  const fieldUpdateByTable = () => {
    // 保存勾选字段后需要重新刷新字段维度度量状态
    const tableList = status.flatState.map((i) => i.node)
    const dimension = []
    const measure = []
    previewData.value = []
    tableList.forEach((tableNode) => {
      tableNode.fields.forEach((f) => {
        const data = {
          fieldId: f.fieldId,
          field: f.field,
          title: f.title,
          tableName: f.tableName,
          dataType: f.dataType,
          type: f.type || "D",
          nodeType: "attribute",
          aggregate: f.aggregate || "SUM",
          format: f.format || "",
          tableId: tableNode.id || tableNode.tableId
        }
        if (f._checked) {
          if (data.type === "D") {
            dimension.push(data)
          } else {
            measure.push(data)
          }
        }
      })
    })
    const field = {
      dimension: {
        title: "维度",
        nodeType: "root",
        children: dimension
      },
      measure: {
        title: "指标",
        nodeType: "root",
        children: measure
      }
    }
    updateFieldState(field)
  }

  // 更新字段数据
  const updateFieldState = (cubeSchema) => {
    const { dimension, measure } = cubeSchema || {}
    // 维度、度量树
    status.dimensionTree = dimension || {
      title: "维度",
      nodeType: "root",
      children: []
    }
    status.measureTree = measure || {
      title: "指标",
      nodeType: "root",
      children: []
    }
    status.dimensionTreeFlats = compileFlatState(status.dimensionTree)
    status.measureTreeFlats = compileFlatState(status.measureTree)
    status.dimensionFields = status.dimensionTreeFlats.filter((v) => v.node.nodeType === "attribute")
    status.measureFields = status.measureTreeFlats.filter((v) => v.node.nodeType === "attribute")
  }

  function allowDrop(draggingNode, dropNode, type) {
    if (dropNode.nodeType === "attribute") {
      return type !== "inner"
    } else {
      return dropNode.nodeType !== "root"
    }
  }

  function allowDrag(draggingNode) {
    // 限制拖拽节点
    return draggingNode.nodeType === "attribute"
  }

  function handleDrop(draggingNode, dropNode, dropType, ev) {
    updateFieldState({
      dimension: status.dimensionTree,
      measure: status.measureTree
    })
  }
  // 初始化数据表
  const initData = async () => {
    //正在加载
    Message.loading("正在加载")
    const resCubeData = await cube.read(dataset.id)
    dataset.name = resCubeData.data.name
    document.title = dataset.name
    const { physical_schema, cube_schema } = resCubeData.data
    tableListLoading.value = true
    const res = await source.datasourceGetTable({
      datasource_id: resCubeData.data.datasource_id
    })
    dataset.datasource_id = resCubeData.data.datasource_id
    tableList.value = res.data || []
    tableListLoading.value = false
    // 表节点树
    status.stateTree = physical_schema || {}
    updateStateTree()
    updateFieldState(cube_schema)
  }

  initData()

  // 保存
  const handleSaveSchema = async () => {
    const modelId = dataset.id
    const physicalSchema = status.stateTree
    const fields = [...status.dimensionTree.children, ...status.measureTree.children].map((f) => ({
      tableId: f.tableId,
      tableName: f.tableName,
      field: f.field,
      fieldId: f.fieldId,
      title: f.title,
      type: f.type,
      dataType: f.dataType,
      aggregate: f.aggregate || "SUM",
      format: f.format || "",
      confType: "empty"
    }))
    try {
      await cube.update(modelId, {
        name: dataset.name,
        physical_schema: physicalSchema,
        fields: fields,
        cube_schema: {
          dimension: status.dimensionTree,
          measure: status.measureTree
        }
      })
      message.success(`保存 [ ${dataset.name} ] 成功`)
    } catch (e) {
      throwError("use-model-data/handleSaveSchema", e)
    }
  }

  // 刷新数据
  const handleRefreshData = async () => {
    Message.loading("正在刷新数据")
    const physicalSchema = status.stateTree
    const fields = [...status.dimensionTree.children, ...status.measureTree.children].map((f) => ({
      tableId: f.tableId,
      tableName: f.tableName,
      field: f.field,
      fieldId: f.fieldId,
      title: f.title,
      type: f.type,
      dataType: f.dataType,
      aggregate: f.aggregate || "SUM",
      format: f.format || "",
      confType: "empty"
    }))

    try {
      const data = await cube.refreshData({
        ...physicalSchema,
        fields,
        datasource_id: dataset.datasource_id
      })
      previewData.value = deepCopy(data.data)
    } catch (e) {
      throwError("use-model-data/handleRefreshData", e)
    }
  }

  return {
    nodeEditRef,
    linkEditRef,
    tableList,
    tableListLoading,
    ...toRefs(status),
    ...toRefs(fieldStatus),
    currentNodeKey,
    currentParentNodeKey,
    previewData,
    addCalField,
    allowDrop,
    allowDrag,
    handleDrop,
    handleNodeClick,
    handleNodeRemove,
    handleNodeDrop,
    handleLinkClick,
    handleEmptyDrop,
    saveSelectedFields,
    saveJoinKeys,
    renderContent,
    handleDmCommand,
    saveField,
    handleSaveSchema,
    handleRefreshData,
    initData,
    convertField
  }
}
